package 
{
	import gs.TweenMax;
	import gs.easing.Quad;

	import com.kvc.extend.papervision3d.CameraRig;

	import org.papervision3d.cameras.CameraType;
	import org.papervision3d.core.clipping.FrustumClipping;
	import org.papervision3d.events.FileLoadEvent;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.materials.shadematerials.EnvMapMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.parsers.DAE;
	import org.papervision3d.objects.primitives.Cube;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.ViewportLayer;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author kevincao
	 */
	[SWF(backgroundColor="0xCCCCCC", width="1000", height="600", frameRate="40")]

	public class CameraRigDemo extends BasicView 
	{

		[Embed(source="../assets/logo/kvcLogo.dae", mimeType="application/octet-stream")]
		private var LogoAsset : Class;

		[Embed(source="../assets/pond.jpg")]
		private var TextureAsset : Class;

		private var logo : DAE;
		private var cube : Cube;
		private var sphere1 : Sphere;		private var sphere2 : Sphere;
		private var envSphere : Sphere;
		private var light : PointLight3D;

		private var vpl : ViewportLayer;

		private var rig : CameraRig;

		public function CameraRigDemo() 
		{
			super(640, 480, true, false, CameraType.FREE);
			init3D();
			
			stage.quality = StageQuality.MEDIUM;
		}

		private function init3D() : void 
		{
			// light
			light = new PointLight3D(false);
			light.z = -10000;
			light.y = 40000;
			light.x = 30000;
			scene.addChild(light);
			
			// texture
			var tex1 : BitmapData = createGrid(256, 256, 0x0, 0xffffff, 5, 5);
			var tex2 : BitmapData = createGrid(256, 256, 0xff0066, 0x3300ff, 1, 12);
			var tex3 : BitmapData = createGrid(256, 256, 0xffff00, 0x00ffff, 1, 6);
			
			cube = new Cube(new MaterialsList({all:new BitmapMaterial(tex1, true)}), 300, 300, 300);
			cube.useClipping = false;
			cube.pitch(30);
			cube.x = randomWithinRange(-500, -1000, false);
			cube.y = randomWithinRange(500, 1000, false);
			cube.z = randomWithinRange(200, 500, true);
			
			sphere1 = new Sphere(new BitmapMaterial(tex2, false), 200, 12, 8);
			sphere1.useClipping = false;
			sphere1.pitch(-30);
			sphere1.x = randomWithinRange(500, 1000, false);			sphere1.y = randomWithinRange(500, 1000, false);			sphere1.z = randomWithinRange(700, 800, true);
			
			sphere2 = new Sphere(new BitmapMaterial(tex3, false), 200, 12, 8);
			sphere2.useClipping = false;
			sphere2.roll(45);
			sphere2.x = randomWithinRange(500, 1000, true);
			sphere2.y = randomWithinRange(-500, -1000, false);
			sphere2.z = randomWithinRange(1000, 1100, true);
			
			scene.addChild(cube);
			scene.addChild(sphere1);
			scene.addChild(sphere2);
			
			vpl = new ViewportLayer(viewport, null);
			vpl.buttonMode = true;
			viewport.containerSprite.addLayer(vpl);
			vpl.getChildLayer(cube).addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);			vpl.getChildLayer(cube).addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			vpl.getChildLayer(cube).addEventListener(MouseEvent.CLICK, clickHandler);
			vpl.getChildLayer(sphere1).addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			vpl.getChildLayer(sphere1).addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			vpl.getChildLayer(sphere1).addEventListener(MouseEvent.CLICK, clickHandler);
			vpl.getChildLayer(sphere2).addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			vpl.getChildLayer(sphere2).addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			vpl.getChildLayer(sphere2).addEventListener(MouseEvent.CLICK, clickHandler);
			
			// logo
			var bmd : BitmapData = (new TextureAsset() as Bitmap).bitmapData;
			bmd.applyFilter(bmd, new Rectangle(0, 0, bmd.width, bmd.height), new Point(), new BlurFilter());
			var mat : EnvMapMaterial = new EnvMapMaterial(light, bmd, bmd, 0xff0000);
			var mList : MaterialsList = new MaterialsList();			mList.addMaterial(mat, "kvcLogoLB");
			logo = new DAE();
			logo.addEventListener(FileLoadEvent.LOAD_COMPLETE, completeHandler);
			logo.load(XML(new LogoAsset()), mList);
			logo.useClipping = false;
			scene.addChild(logo);
			 
			// environment sphere
			bmd = (new TextureAsset() as Bitmap).bitmapData;
			envSphere = new Sphere(new BitmapMaterial(bmd), 4500, 12, 12);
			envSphere.material.doubleSided = true;
			scene.addChild(envSphere);
			
			// camera
			camera.focus = 120;
			camera.zoom = 3;
			
			// rig
			rig = new CameraRig(camera, scene);
			rig.tracking = 3000;
			rig.heading = -45;
			rig.pitch = 45;
			
			renderer.clipping = new FrustumClipping(FrustumClipping.NEAR);
		}

		private function completeHandler(event : FileLoadEvent) : void 
		{
			logo.removeEventListener(FileLoadEvent.LOAD_COMPLETE, completeHandler);
			
			var logoLayer : ViewportLayer = vpl.getChildLayer(logo, true, true);
			logoLayer.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			logoLayer.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			logoLayer.addEventListener(MouseEvent.CLICK, clickHandler);
			
			tween(logo);
			
			addEventListener(Event.ENTER_FRAME, tick);
		}

		private function clickHandler(event : MouseEvent) : void
		{
			tween(ViewportLayer(event.target).displayObject3D);
		}

		private function rollOverHandler(event : MouseEvent) : void
		{
			event.target.filters = [new GlowFilter(0xffffff, 1, 10, 10, 4)];
		}

		private function rollOutHandler(event : MouseEvent) : void
		{
			event.target.filters = null;
		}

		private function tween(do3d : DisplayObject3D) : void 
		{
			TweenMax.to(rig, 2, {heading:randomWithinRange(-360, 360), pitch:randomWithinRange(-40, 40), bank:randomWithinRange(-30, 30), tracking:randomWithinRange(500, 1200), x:do3d.x, y:do3d.y, z:do3d.z, ease:Quad.easeInOut});
		}

		private function tick(event : Event) : void 
		{
			if(!TweenMax.isTweening(rig)) {				var vx : Number = viewport.containerSprite.mouseX;				var vy : Number = viewport.containerSprite.mouseY;
				rig.heading += vx * 0.002;				rig.pitch += -vy * 0.002;
			}
			
			rig.update();
			singleRender();
		}

		private function createGrid(width : int, height : int, color1 : uint = 0x0, color2 : uint = 0xffffff, gridX : Number = 5, gridY : Number = 5) : BitmapData 
		{
			var bitmapData : BitmapData = new BitmapData(width, height);
			var cellWidth : Number = width / gridX;
			var cellHeight : Number = height / gridY;
			var canvas : Shape = new Shape();
			var swap : Boolean;
			for (var i : int = 0;i < gridX; i++) {
				swap = i % 2 ? true : false;
				for (var j : int = 0;j < gridY; j++) {
					canvas.graphics.beginFill(j % 2 ? (swap ? color1 : color2) : (swap ? color2 : color1));
					canvas.graphics.drawRect(i * cellWidth, j * cellHeight, cellWidth, cellHeight);
					canvas.graphics.endFill();
				}
			}
			bitmapData.draw(canvas);
			return bitmapData;
		}

		private function randomWithinRange(min : Number, max : Number, mirror : Boolean = false) : Number 
		{
			return (mirror && Math.random() < 0.5 ? -1 : 1) * (min + (Math.random() * (max - min)));
		}
	}
}
